﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Text.RegularExpressions;


namespace Device
{
    /// <summary>
    /// 
    /// </summary>
    public static class ServerProtocolEncode
    {
        /// <summary>
        /// 组建握手包
        /// </summary>
        /// <param name="localId">ServerId字节数组</param>
        /// <param name="payLoad">数据包内容</param>
        /// <returns>握手包</returns>
        public static byte[] GenHandShake(byte[] localId, byte[] payLoad)
        {
            List<byte> bList = new List<byte>();
            if (localId != null)
            {
                var header = new byte[] { 0xfc };
                var type = new byte[] { 0x01 };
                UInt16 length = 0;
                if (payLoad != null)
                {
                    length = Convert.ToUInt16((ushort)payLoad.Length);
                }
                var bLen = StringHexByteUtils.Uint16ToBytes(length);
                bList.AddRange(header);
                bList.AddRange(type);
                bList.AddRange(new byte[] { 0xff, 0xff, 0xff, 0xff });
                bList.AddRange(localId);
                bList.AddRange(bLen.Reverse());

                if (payLoad != null) bList.AddRange(payLoad);
                var crc = CRC16_modbus_utils.CRC16_modbus(bList.ToArray());
                var bCrc = StringHexByteUtils.Uint16ToBytes(crc).Reverse().ToArray();
                bList.AddRange(bCrc);
                return bList.ToArray();
            }

            return null;
        }

        /// <summary>
        /// 组建心跳包
        /// </summary>
        /// <param name="bAnchorId">基站编号字节数组</param>
        /// <param name="bServerId">服务器ID字节数组</param> 
        /// <returns>用于保持连接的心跳包</returns>
        public static byte[] GenHeartBeat(byte[] bAnchorId, byte[] bServerId)
        {
            if (bServerId == null) { bServerId = Global.bServerId; }
            if (bAnchorId == null) { bAnchorId = new byte[] { 0xff, 0xff, 0xff, 0xff }; }

            byte[] header = new byte[] { 0xfc };
            byte[] btype = new byte[] { 0x03 };
            byte[] bCrc = new byte[] { 0xff, 0xff };


            int stamp = GetTimeStamp();
            var bStamp = BitConverter.GetBytes(stamp);
            var list = new List<byte>();
            list.Add(0x0f);
            list.Add(0x04);
            list.AddRange(bStamp);
            UInt16 payloadLen = 0;
            payloadLen = Convert.ToUInt16(list.Count);
            var bLen = StringHexByteUtils.Uint16ToBytes(payloadLen);
            List<byte> bList = new List<byte>();
            bList.AddRange(header);
            bList.AddRange(btype);
            bList.AddRange(bAnchorId);
            bList.AddRange(bServerId);
            bList.AddRange(bLen.Reverse());
            bList.AddRange(list);
            bCrc = StringHexByteUtils.Uint16ToBytes(CRC16_modbus_utils.CRC16_modbus(bList.ToArray())).Reverse().ToArray();
            bList.AddRange(bCrc);
            return bList.ToArray();
        }

        /// <summary>
        /// 读取基站参数
        /// </summary>
        /// <param name="bAnchorId">基站编号</param>
        /// <param name="bServerId">服务器编号</param>
        /// <param name="payLoad">组织的参数字节数组</param>
        /// <returns>基站参数读取协议数据包</returns>
        public static byte[] GenReadAnchor(byte[] bAnchorId, byte[] bServerId, byte[] payLoad)
        {
            if (bAnchorId != null
              && bAnchorId.Length == 4
              && bServerId != null
              && bServerId.Length == 4
              )
            {
                byte[] header = new byte[] { 0xfc };
                byte[] btype = new byte[] { 0x11 };
                byte[] bCrc = { 0xff, 0xff };

                List<byte> bList = new List<byte>();
                bList.AddRange(header);
                bList.AddRange(btype);
                bList.AddRange(bAnchorId);
                bList.AddRange(bServerId);
                UInt16 payloadLen = 0;
                if (payLoad != null)
                {
                    payloadLen = Convert.ToUInt16(payLoad.Length);
                }
                var bLen = StringHexByteUtils.Uint16ToBytes(payloadLen);
                bList.AddRange(bLen.Reverse());
                if (payLoad != null) { bList.AddRange(payLoad); }
                bCrc = StringHexByteUtils.Uint16ToBytes(CRC16_modbus_utils.CRC16_modbus(bList.ToArray())).Reverse().ToArray();
                bList.AddRange(bCrc);
                return bList.ToArray();
            }
            return null;
        }

        /// <summary>
        /// 设置基站参数
        /// </summary>
        /// <param name="bAnchorId">基站编号字节数组</param>
        /// <param name="bServerId">服务器编号字节数组</param>
        /// <param name="payLoad">参数字节数组</param>
        /// <returns>基站设置协议数据包</returns>
        public static byte[] GenSetAnchorParams(byte[] bAnchorId, byte[] bServerId, byte[] payLoad)
        {
            if (bAnchorId != null
                 && bAnchorId.Length == 4
                 && bServerId != null
                 && bServerId.Length == 4
                 )
            {
                byte[] header = new byte[] { 0xfc };
                byte[] btype = new byte[] { 0x13 };
                byte[] bCrc = new byte[] { 0xff, 0xff };
                byte[] blen = StringHexByteUtils.Uint16ToBytes(Convert.ToUInt16(payLoad.Length)).Reverse().ToArray();
                List<byte> bList = new List<byte>();
                bList.AddRange(header);
                bList.AddRange(btype);
                bList.AddRange(bAnchorId);
                bList.AddRange(bServerId);
                bList.AddRange(blen);
                if (payLoad != null) { bList.AddRange(payLoad); }
                bCrc = StringHexByteUtils.Uint16ToBytes(CRC16_modbus_utils.CRC16_modbus(bList.ToArray())).Reverse().ToArray(); ;
                bList.AddRange(bCrc);
                return bList.ToArray();
            }

            return null;
        }

        /// <summary>
        /// 获取保存于基站内的基站列表信息
        /// </summary>
        /// <param name="bAnchorId">基站编号</param>
        /// <param name="bServerID">服务器编号</param>
        /// <returns>获取基站列表协议数据包</returns>
        public static byte[] GenCodeGetAnchorList(byte[] bAnchorId, byte[] bServerID)
        {
            AnchorSettingProtocol asp = new AnchorSettingProtocol
            {
                RemoteId = bAnchorId,
                LocalId = bServerID,
                Payload = new List<Tlv> { new Tlv { type = 0x10, length = 0x00 } }
            };
            asp.type = 0x11;
            var data = EncodeProtocol(asp);
            return data;
        }

        /// <summary>
        /// 生成设置WIFI的协议数据包
        /// </summary>
        /// <param name="anchorid">基站编号</param>
        /// <param name="ssid">WIFI的SSID</param>
        /// <param name="password">WIFI密码</param>
        /// <returns>设置基站WIFI网络协议数据包</returns>
        public static byte[] GenSetWifiCode(string anchorid, string ssid, string password)
        {
            byte[] cmd = null;
            var bSsid = Encoding.ASCII.GetBytes(ssid);
            var bPassword = Encoding.ASCII.GetBytes(password);

            var ssidTlv = new Tlv { type = 0x20, length = (byte)bSsid.Length, value = bSsid };
            var pwdTlv = new Tlv { type = 0x21, length = (byte)bPassword.Length, value = bPassword };

            List<Tlv> tlvs = new List<Tlv>();
            tlvs.Add(ssidTlv);
            tlvs.Add(pwdTlv);

            AnchorSettingProtocol asp = new AnchorSettingProtocol
            {
                RemoteId = StringHexByteUtils.HexStringToByte(FormatHexStr(anchorid)),
                LocalId = Global.bServerId,
                Payload = tlvs
            };
            cmd = EncodeProtocol(asp);
            return cmd;

        }

        /// <summary>
        /// (私有的)对基站设置相关的属性进行数据包转换
        /// </summary>
        /// <param name="asp">基站设置协议参数</param>
        /// <returns>基站设置数据包</returns>
        private static byte[] EncodeProtocol(AnchorSettingProtocol asp)
        {
            List<byte> bList = new List<byte>();
            List<byte> bPayload = new List<byte>();
            bList.Add(asp.Header);
            bList.Add(asp.type);
            bList.AddRange(asp.RemoteId);
            bList.AddRange(asp.LocalId);
            foreach (var tlv in asp.Payload)
            {
                bPayload.Add(tlv.type);
                bPayload.Add(tlv.length);
                if (tlv.value != null)
                {
                    bPayload.AddRange(tlv.value);

                }
            }
            bList.AddRange(StringHexByteUtils.int16ToBytes((short)bPayload.Count).Reverse());
            bList.AddRange(bPayload);
            var crc = CRC16_modbus_utils.CRC16_modbus(bList.ToArray());
            bList.AddRange(StringHexByteUtils.Uint16ToBytes(crc).Reverse());
            return bList.ToArray();
        }

        /// <summary>
        /// 读取标签参数
        /// </summary>
        /// <param name="bAnchorId">基站编号</param>
        /// <param name="bServerId">服务器编号</param>
        /// <param name="payLoad">数据帧</param>
        /// <returns>读取标签参数协议数据包</returns>
        public static byte[] GenGetTagParams(byte[] bAnchorId, byte[] bServerId, byte[] payLoad)
        {
            if (bAnchorId != null
                  && bAnchorId.Length == 4
                  && bServerId != null
                  && bServerId.Length == 4
                  )
            {
                byte[] header = new byte[] { 0xfc };
                byte[] btype = new byte[] { 0x15 };
                byte[] bCrc = new byte[] { 0xff, 0xff };

                List<byte> bList = new List<byte>();
                bList.AddRange(header);
                bList.AddRange(btype);
                bList.AddRange(bAnchorId);
                bList.AddRange(bServerId);
                byte[] blen = StringHexByteUtils.Uint16ToBytes(Convert.ToUInt16(payLoad.Length)).Reverse().ToArray();
                bList.AddRange(blen);
                if (payLoad != null) { bList.AddRange(payLoad); }
                bCrc = StringHexByteUtils.Uint16ToBytes(CRC16_modbus_utils.CRC16_modbus(bList.ToArray())).Reverse().ToArray();
                bList.AddRange(bCrc);
                return bList.ToArray();
            }

            return null;

        }

        /// <summary>
        /// 设置tag参数
        /// </summary>
        /// <param name="bAnchorId">基站编号</param>
        /// <param name="bServerId">服务器编号</param>
        /// <param name="payLoad">数据帧</param>
        /// <returns>标签设置协议数据包</returns>
        public static byte[] GenSetTagParams(byte[] bAnchorId, byte[] bServerId, byte[] payLoad)
        {
            if (bAnchorId != null
               && bAnchorId.Length == 4
               && bServerId != null
               && bServerId.Length == 4
               )
            {
                byte[] header = new byte[] { 0xfc };
                byte[] btype = new byte[] { 0x17 };
                byte[] bCrc = new byte[] { 0xff, 0xff };
                List<byte> bList = new List<byte>();
                bList.AddRange(header);
                bList.AddRange(btype);
                bList.AddRange(bAnchorId);
                bList.AddRange(bServerId);
                byte[] blen = StringHexByteUtils.Uint16ToBytes(Convert.ToUInt16(payLoad.Length)).Reverse().ToArray();
                bList.AddRange(blen);
                if (payLoad != null) { bList.AddRange(payLoad); }
                bCrc = StringHexByteUtils.Uint16ToBytes(CRC16_modbus_utils.CRC16_modbus(bList.ToArray())).Reverse().ToArray();
                bList.AddRange(bCrc);
                return bList.ToArray();
            }
            return null;
        }

        /// <summary>
        /// 生成基站设置数据包
        /// </summary>
        /// <param name="anchorid">基站编号</param>
        /// <param name="serverid">服务器编号</param>
        /// <param name="tlvs">配置数据</param>
        /// <returns>基站设置数据包</returns>
        private static byte[] GenSetAnchorCmd(string anchorid, string serverid, List<Tlv> tlvs)
        {
            var bAnchorid = StringHexByteUtils.HexStringToByte(FormatHexStr(anchorid));
            var bServerId = Global.bServerId;
            var payload = PacketTlvList(tlvs);
            byte header = 0xfc;
            byte functionCode = 0x13;
            List<byte> cmdList = new List<byte>();
            cmdList.Add(header);
            cmdList.Add(functionCode);
            cmdList.AddRange(bAnchorid);
            cmdList.AddRange(Global.bServerId);
            cmdList.AddRange(StringHexByteUtils.Uint16ToBytes((ushort)payload.Length).Reverse());
            cmdList.AddRange(payload);
            var bCrc = StringHexByteUtils.Uint16ToBytes(CRC16_modbus_utils.CRC16_modbus(cmdList.ToArray())).Reverse().ToArray();
            cmdList.AddRange(bCrc);
            return cmdList.ToArray();
        }

        private static byte[] GenSetAnchorCmd(byte[] anchorid, byte[] serverid, List<Tlv> tlvs)
        {
            var payload = PacketTlvList(tlvs);
            byte header = 0xfc;
            byte functionCode = 0x13;
            List<byte> cmdList = new List<byte>();
            cmdList.Add(header);
            cmdList.Add(functionCode);
            cmdList.AddRange(anchorid);
            cmdList.AddRange(serverid);
            cmdList.AddRange(StringHexByteUtils.Uint16ToBytes((ushort)payload.Length).Reverse());
            cmdList.AddRange(payload);
            var bCrc = StringHexByteUtils.Uint16ToBytes(CRC16_modbus_utils.CRC16_modbus(cmdList.ToArray())).Reverse().ToArray();
            cmdList.AddRange(bCrc);
            return cmdList.ToArray();
        }


        /// <summary>
        /// 下发时间数据
        /// </summary>
        /// <param name="anchorid">基站编号</param>
        /// <param name="serverid">服务器编号</param>
        /// <returns></returns>
        public static byte[] GetSetDatetimeParams(string anchorid, string serverid)
        {
            byte[] value = BitConverter.GetBytes(GetTimeStamp());
            byte type = 0x0f;
            byte len = 0x04;

            Tlv tlv = new Tlv { type = type, length = len, value = value };
            List<Tlv> tlvs = new List<Tlv> { tlv };
            return GenSetAnchorCmd(anchorid, serverid, tlvs);
        }

        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns>时间戳（秒单位）</returns>
        public static Int32 GetTimeStamp()
        {
            //DateTime.Now获取的是电脑上的当前时间
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt32(ts.TotalSeconds);
        }


        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns>时间戳（毫秒单位）</returns>
        public static double GetTimeStampMilliseconds()
        {
            //DateTime.Now获取的是电脑上的当前时间
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return ts.TotalMilliseconds;
        }


        /// <summary>
        /// 周边基站列表设置命令
        /// </summary>
        /// <param name="anchorid">基站编号</param>
        /// <param name="serverid">服务器编号</param>
        /// <param name="anchorlist">基站列表</param>
        /// <returns>基站列表设置协议数据包</returns>
        public static byte[] GenSetAnchorListPackage(string anchorid, string serverid, string[] anchorlist)
        {
            if (string.IsNullOrEmpty(anchorid) || string.IsNullOrEmpty(serverid))
            {
                return null;
            }
            var bAnchorid = StringHexByteUtils.HexStringToByte(FormatHexStr(anchorid));
            var bServerId = Global.bServerId;
            byte header = 0xfc;
            byte type = 0x13;
            byte[] payload = GenSetAnchorListParams(anchorlist);
            List<byte> cmdList = new List<byte>();
            cmdList.Add(header);
            cmdList.Add(type);
            cmdList.AddRange(bAnchorid);
            cmdList.AddRange(bServerId);
            if (payload != null)
            {
                cmdList.AddRange(StringHexByteUtils.Uint16ToBytes((UInt16)payload.Length).Reverse());

                cmdList.AddRange(payload);
            }
            else
            {
                cmdList.AddRange(new byte[] { 0x00, 0x00 });
            }

            var bCrc = StringHexByteUtils.Uint16ToBytes(CRC16_modbus_utils.CRC16_modbus(cmdList.ToArray())).Reverse().ToArray();
            cmdList.AddRange(bCrc);
            return cmdList.ToArray();
        }

        /// <summary>
        /// 生成Anchorlist payload
        /// </summary>
        /// <param name="anchorList">基站列表</param>
        /// <returns></returns>
        private static byte[] GenSetAnchorListParams(string[] anchorList)
        {
            if (anchorList.Length <= 0)
            {
                return new byte[] { 0x12, 0x00 };
            }
            List<byte> blist = new List<byte>();

            for (int i = 0; i < anchorList.Length; i++)
            {
                string hexId = FormatHexStr(anchorList[i]);
                byte[] bHexId = StringHexByteUtils.HexStringToByte(hexId);
                blist.Add((byte)(0x12 + i));
                blist.Add(0x04);
                blist.AddRange(bHexId);
            }

            return blist.ToArray();
        }

        private static string FormatHexStr(string str)
        {
            str = str.Replace(" ", "");
            if (str.Length % 2 > 0)
            {
                str = "0" + str;
            }
            var s = string.Join(" ", Regex.Matches(str, @"..").Cast<Match>().ToList());
            return s;
        }

        /// <summary>
        /// OTA升级通知协议
        /// </summary>
        /// <param name="anchorid">基站编号</param>
        /// <param name="serverid">服务器编号
        /// </param>
        /// <returns></returns>
        public static byte[] GenOTACmdForAnchor(string anchorid, string serverid, string filename)
        {
            if (!string.IsNullOrEmpty(anchorid) && !string.IsNullOrEmpty(serverid))
            {
                byte header = 0xFB;
                byte type = 0x05;
                byte[] bAnchid = StringHexByteUtils.HexStringToByte(FormatHexStr(anchorid));
                byte[] bServerId = Global.bServerId;
                byte[] asciiFilename = Encoding.ASCII.GetBytes(filename);
                byte[] payload = asciiFilename;
                byte[] tlv = CreateTlv(0x01, payload);
                byte[] blen = StringHexByteUtils.Uint16ToBytes(Convert.ToUInt16(tlv.Length)).Reverse().ToArray();
                List<byte> list = new List<byte>();
                list.Add(header);
                list.Add(type);
                list.AddRange(bAnchid);
                list.AddRange(bServerId);
                list.AddRange(blen);
                list.AddRange(tlv);
                byte[] bCrc = StringHexByteUtils.Uint16ToBytes(CRC16_modbus_utils.CRC16_modbus(list.ToArray())).Reverse().ToArray();
                list.AddRange(bCrc);
                return list.ToArray();
            }
            return null;
        }

        /// <summary>
        /// IP地址转换为字节数组
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static byte[] IpToBytes(string ip)
        {
            string[] ipSection = ip.Split(".");
            List<byte> bList = new List<byte>();
            for (int i = 0; i < ipSection.Length; i++)
            {
                byte b = Convert.ToByte(ipSection[i]);
                bList.Add(b);
            }
            return bList.ToArray();
        }


        private static byte[] CreateTlv(byte t, byte[] v)
        {
            List<byte> list = new List<byte>();
            list.Add(t);
            list.Add(Convert.ToByte(v.Length));
            list.AddRange(v);
            return list.ToArray();
        }


        public static byte[] PacketTlvList(List<Tlv> tlvList)
        {
            List<byte> blist = new List<byte>();
            foreach (var tlv in tlvList)
            {

                blist.Add(tlv.type);
                blist.Add(tlv.length);
                if (tlv.value != null)
                {
                    blist.AddRange(tlv.value);
                }
            }
            return blist.ToArray();
        }

        /// <summary>
        /// Log查看请求
        /// </summary>
        /// <param name="anchorid"></param>
        /// <param name="serverid"></param>
        /// <returns></returns>
        public static byte[] GenLogRequest(string anchorid, string serverid)
        {
            AnchorSettingProtocol asp = new AnchorSettingProtocol();
            asp.Header = 0xfc;
            asp.type = 0xE1;
            asp.RemoteId = StringHexByteUtils.HexStringToByte(FormatHexStr(anchorid));
            asp.LocalId = Global.bServerId;
            List<byte> bCmd = new List<byte>();
            Tlv tlv = new Tlv();
            tlv.type = 0x01;
            tlv.length = 0x00;
            asp.Payload = new List<Tlv> { tlv };
            var cmd = EncodeProtocol(asp);
            return cmd;
        }

        /// <summary>
        /// 构建注册回复帧
        /// </summary>
        /// <param name="anchorid">基站ID</param>
        /// <param name="serverid">ServerID</param>
        /// <param name="tagid">标签ID</param>
        /// <param name="isAllow">是否同意注册</param>
        /// <param name="staticType">静止模式</param>
        /// <param name="workMode">工作模式（点对点，两点定位，三点定位）</param>
        /// <returns></returns>
        public static byte[] GenTagRegResponse(string anchorid, string serverid, string tagid, bool isAllow, int staticType = 0, int workMode = 0)
        {
            byte header = 0xfc;
            byte type = 0x0d;
            byte[] remoteId = StringHexByteUtils.HexStringToByte(StringHexByteUtils.FormatHexStr(anchorid));
            byte[] localId = Global.bServerId;
            List<Tlv> tlvs = new List<Tlv>
            {
                new Tlv
                {
                    type = 0x01,
                    length = 4,
                    value = StringHexByteUtils.HexStringToByte(StringHexByteUtils.FormatHexStr(tagid))
                },
                new Tlv{ type=0x03,length=1,value=isAllow==true?new byte[]{ 0x01} :new byte[]{ 0x02} },

            };
            if (isAllow)
            {
                tlvs.Add(new Tlv
                {
                    type = 0x04,
                    length = 1,
                    value = new byte[] { (byte)staticType }
                });
                tlvs.Add(new Tlv
                {
                    type = 0x05,
                    length = 1,
                    value = new byte[] { (byte)workMode }
                });
            }
            AnchorSettingProtocol asp = new AnchorSettingProtocol();
            asp.Header = header;
            asp.type = type;
            asp.RemoteId = remoteId;
            asp.LocalId = Global.bServerId;
            asp.Payload = tlvs;
            var cmd = EncodeProtocol(asp);
            return cmd;
        }


        /// <summary>
        /// 设置标签心跳定位（静止时以心跳包代替测距包）
        /// </summary>
        /// <param name="anchorid">基站编号</param>
        /// <param name="serverid">服务器编号</param>
        /// <param name="IsHeartBeatLocation">是否打开心跳定位</param>
        /// <returns>心跳定位协议包</returns>
        public static byte[] GenTagHeartBeatLocation(string anchorid, string serverid, bool IsHeartBeatLocation)
        {
            byte[] bValue = IsHeartBeatLocation ? new byte[] { 0x01 } : new byte[] { 0x02 };
            var tlvList = new List<Tlv>()
                         {
                             new Tlv{ type=0x24, length=0x01, value=bValue}
                         };
            var data = ServerProtocolEncode.GenSetAnchorCmd(anchorid, serverid, tlvList);
            return data;
        }

        /// <summary>
        /// 生成标签人机交互命令
        /// </summary>
        /// <param name="anchorid">基站编号</param> 
        /// <param name="tagid">标签编号</param>
        /// <param name="actionSet">动作设置（时间间隔）</param>
        /// <param name="attr">动作特征码（位操作）</param>
        /// <returns>标签人机交互协议</returns>
        public static byte[] GenTagAction(string anchorid, string tagid, byte actionSet, byte attr)
        {
            byte[] bServerid = Global.bServerId;
            byte[] bAnchorId = StringHexByteUtils.HexStringToByte(StringHexByteUtils.FormatHexStr(anchorid));
            byte[] bTagId = StringHexByteUtils.HexStringToByte(StringHexByteUtils.FormatHexStr(tagid));
            var tlvList = new List<Tlv>();

            tlvList.Add(new Tlv { type = 0x01, length = 0x04, value = bTagId });
            tlvList.Add(new Tlv { type = 0x08, length = 0x01, value = new byte[] { actionSet } });
            tlvList.Add(new Tlv { type = 0x09, length = 0x01, value = new byte[] { attr } });


            AnchorSettingProtocol asp = new AnchorSettingProtocol();
            asp.Header = 0xfc;
            asp.type = 0x32;
            asp.RemoteId = StringHexByteUtils.HexStringToByte(FormatHexStr(anchorid));
            asp.LocalId = bServerid;

            asp.Payload = tlvList;
            var cmd = EncodeProtocol(asp);
            return cmd;
        }
    }
}
